/******************************************************************************
** 公司名称：天津柯迪斯科技有限公司
** 版权信息：
** 文件名称： App_Protocol_KDS_CAN_V13.c
** 模块名称： 柯迪斯CAN-V1.3协议处理模块
** 版 本 号： V1.0
** 作    者： 蒲磊
**
** 修改记录： 版本     修改人      时间         修改内容
**
******************************************************************************/

/******************************************************************************
* 头文件
******************************************************************************/
#include <string.h>
#include "Config.h"
#include "App_Protocol.h"
#include "App_MainTask.h"
#include "App_Parameter.h"
#include "multi_cyc_fifo.h"
#include "bsp.h"
/******************************************************************************
* 本文件宏定义 ('#define')
******************************************************************************/

/******************************************************************************
* 本文件类型定义 ('typedef')
******************************************************************************/

/******************************************************************************
* 本文件静态函数声明 ('static')
******************************************************************************/
static void vCAN_Receive_Message(can_rx_message_type *pCanRxMsg,strBikeInfo *pBikeInfo);
static void vCan_Send_DisplayMessage(uint32_t ID,uint8_t Cmd,strBikeInfo   *pBikeInfo);
static void vCan_Send_Message(void);
static void vPROTOCOL_Factory_Response(uint32_t Cmd,uint16_t Data);
static uint8_t ucSummation_Check(uint8_t ID,uint8_t *pBuffer,uint16_t Length);
/******************************************************************************
* 全局变量定义
******************************************************************************/
strBikeInfo             gxBikeInfo = {0};         /*车辆数据*/
static uint32_t         gulCommunicationCnt = 0;
enSEND_DATA_TYPE		geSend_Data_Type 	= Send_Stop;
uint8_t                 gucReceivedConfigFrame = 0;/*是否已接收到配置帧标记*/
uint8_t                 gucRequestSendConfigData = 0;/*请求发送配置帧标记*/
/*****************************************************************************
* 函数实现 - global ('extern') and local ('static')
******************************************************************************/

/******************************************************************************
** 功  能：CAN协议初始化函数
** 参  数：无
** 返回值：无
** 备  注：用于初始化CAN协议模块的相关变量，同时创建收发队列。
******************************************************************************/
void vPROTOCOL_Init(void)
{
    muilt_cyc_fifo_error_code_t    lxState;
    MCF_ApplyFifo(gxCAN_RxQueue_Len,gxCAN_RxQueue,&lxState);     /*初始化接收队列*/
    MCF_ApplyFifo(gxCAN_TxQueue_Len,gxCAN_TxQueue,&lxState);     /*初始化发送队列*/
    gxBikeInfo.Battery.Soc = -1;    /*初始化电池电量值为-1，用于判断是否能读取到电池的SOC*/
}

/******************************************************************************
** 功  能：计算和校验
** 参  数：ID-参与校验的帧ID，pBuffer-指向数据区指针，Length-数据长度
** 返回值：校验值
** 备  注：8位的和校验
******************************************************************************/
static uint8_t ucSummation_Check(uint8_t ID,uint8_t *pBuffer,uint16_t Length)
{
    uint8_t Sum = ID;
    while(Length > 0)
    {
        Sum += *pBuffer;
        pBuffer++;
        Length--;
    }
    return Sum;
}

/******************************************************************************
** 功  能：将接收到的Can帧解析为用户的Can数据结构
** 参  数：pCanMessage-接收到的Can数据结构体指针
** 返回值：无
** 备  注：该函数是整个Can协议模块的入口函数。当CAN总线接收一帧Can数据后，调用该函数，
**        将Can消息帧转换为用户的CAN数据格式，并且放入接收队列
******************************************************************************/
void vCAN_CanMsgToUserMsg(can_rx_message_type *pCanMessage)
{

    muilt_cyc_fifo_error_code_t lxState;

    /*柯迪斯CAN协议，无需转换，直接将Can数据放入FIFO队列*/
    MCF_WriteDataInFifo(gxCAN_RxQueue,(uint8_t *)pCanMessage,sizeof(can_rx_message_type),&lxState);
}




/******************************************************************************
** 功  能：CAN协议轮询，处理收发
** 参  数：无
** 返回值：无
** 备  注：该函数是模块主函数，应定时调用，调用周期一般10-20ms，定时处理收发
******************************************************************************/
void vPROTOCOL_Loop(void)
{
    static uint32_t lulTicks = 0;
    uint8_t lucChecksum;
    can_rx_message_type     lxCanRxMsg;
    can_tx_message_type     lxCanTxMsg;
    muilt_cyc_fifo_error_code_t lxState;
    uint16_t lxFifoCanReadLen;
    uint16_t lxActualReadLen;


    /*500ms发送一次数据*/
    if(lulTicks % (500 / CAN_LOOP_CYCLE) == 0)
    {
        vCan_Send_Message();                                    /*发送运行信息或者配置信息*/
        vCan_Send_DisplayMessage(ID_BMS,0x22,&gxBikeInfo);      /*发送读取电池电量信息*/
    }

    lulTicks++;
    gulCommunicationCnt++;

    /*10S之内，通信超时变量未复位，报30错误*/
    if(gulCommunicationCnt > (10000 / CAN_LOOP_CYCLE))
    {
        gxBikeInfo.ErrCode = 0x30;
    }
    else
    {
        if(gxBikeInfo.ErrCode == 0x30)
        {
            gxBikeInfo.ErrCode = 0;
        }
    }

    /*判断接收队列是否非空*/
    MCF_GetCanReadLen(gxCAN_RxQueue,&lxFifoCanReadLen,&lxState);
    if(lxState == kMultiCycFiFo_Error_NONE && lxFifoCanReadLen > 0)
    {
        MCF_ReadDataFromFifo(gxCAN_RxQueue,sizeof(can_rx_message_type),(uint8_t *)&lxCanRxMsg,&lxActualReadLen,&lxState);/*从队列中取出一组CAN数据*/
        if(lxActualReadLen == sizeof(can_rx_message_type) && lxState == kMultiCycFiFo_Error_NONE)
        {
            /*计算校验值*/
            lucChecksum = ucSummation_Check(lxCanRxMsg.standard_id,lxCanRxMsg.data,lxCanRxMsg.dlc - 1);
            /*校验值正确，认为数据有效，复位通信超时计数，并且根据ID进行解析*/
            if(lucChecksum == lxCanRxMsg.data[7])
            {
                gulCommunicationCnt = 0;        /*复位通信超时计数*/
                /*判断目的节点*/
                switch(lxCanRxMsg.standard_id)
                {
                case ID_DP:                 /*发给仪表的消息*/
                {
                    vCAN_Receive_Message(&lxCanRxMsg,&gxBikeInfo);
                    break;
                }
                default:
                    break;              /*其它消息不接收*/
                }
            }
        }
    }

    /*判断发送缓冲区是否有数据需要发送*/
    MCF_GetCanReadLen(gxCAN_TxQueue,&lxFifoCanReadLen,&lxState);
    if(lxState == kMultiCycFiFo_Error_NONE && lxFifoCanReadLen > 0)
    {
        MCF_ReadDataFromFifo(gxCAN_TxQueue,sizeof(can_tx_message_type),(uint8_t *)&lxCanTxMsg,&lxActualReadLen,&lxState);/*从队列中取出一组CAN数据*/
        if(lxActualReadLen == sizeof(can_tx_message_type) && lxState == kMultiCycFiFo_Error_NONE)
        {
            can_message_transmit(CAN1,&lxCanTxMsg);     /*调用系统库函数进行发送*/
        }
    }
}

/******************************************************************************
** 功  能：接收处理源节点为控制器的消息
** 参  数：pBFCanMsg-接收到的Can消息指针，pBikeInfo-车辆信息结构体指针
** 返回值：无
** 备  注：
******************************************************************************/
static void vCAN_Receive_Message(can_rx_message_type *pCanRxMsg,strBikeInfo *pBikeInfo)
{

    switch(pCanRxMsg->data[0])
    {
    case 0x43:          /*控制器返回的参数配置状态*/
    {
        if(pCanRxMsg->data[1] == 0)
        {
            gucReceivedConfigFrame = 1;
        }
        break;
    }
    case 0x4F:          /*控制器发送的运行状态帧*/
    {
        pBikeInfo->MCU.Current   = pCanRxMsg->data[1];        /*运行电流*/
        pBikeInfo->MCU.Speed_Cnt = ((uint16_t)pCanRxMsg->data[2] << 8) | pCanRxMsg->data[3];    /*车轮转动一周的时间，ms，最大3500，0x0DAC*/
        pBikeInfo->MCU.ErrorCode = pCanRxMsg->data[4];        /*错误代码*/
        break;
    }
    case 0x22:          /*电池上传的电量信息*/
    {
        pBikeInfo->Battery.Soc = pCanRxMsg->data[1];        /*SOC*/
        break;
    }
    case 0x26:          /*电池上传的详细信息*/
    {
        pBikeInfo->Battery.Voltage = ((uint16_t)pCanRxMsg->data[1] << 8) | pCanRxMsg->data[2];      /*电压，mv*/
        pBikeInfo->Battery.Current = ((int16_t)pCanRxMsg->data[3] << 8) | pCanRxMsg->data[4];       /*电流，mA，有符号*/
        break;
    }

    default:
    {
        break;
    }
    }
}



/******************************************************************************
** 功  能：仪表发送消息
** 参  数：ID-要发送的帧ID，Cmd-命令类型，pBikeInfo-车辆信息结构体指针
** 返回值：无
** 备  注：
******************************************************************************/
static void vCan_Send_DisplayMessage(uint32_t ID,uint8_t Cmd,strBikeInfo   *pBikeInfo)
{
    can_tx_message_type         lxCanTxMsg;
    muilt_cyc_fifo_error_code_t lxState;


    lxCanTxMsg.id_type     = CAN_ID_STANDARD;
    lxCanTxMsg.frame_type  = CAN_TFT_DATA;
    lxCanTxMsg.standard_id = ID;
    lxCanTxMsg.dlc         = 8;
    lxCanTxMsg.data[0]     = Cmd;


    switch(Cmd)
    {
    case 0x43:/*仪表写配置参数*/
    {
        lxCanTxMsg.data[1] = pBikeInfo->Display.WheelSize;
        lxCanTxMsg.data[2] = pBikeInfo->Display.Speed_Limit;
        lxCanTxMsg.data[3] = pBikeInfo->Display.Current_Limit;
        lxCanTxMsg.data[4] = (pBikeInfo->Display.Handle_Segement << 7) | (pBikeInfo->Display.Handle_Walk << 6) | (pBikeInfo->Display.Speed_Sensor_Num);
        lxCanTxMsg.data[5] = (pBikeInfo->Display.Slow_Start << 5) | pBikeInfo->Display.Assistant_Num;
        lxCanTxMsg.data[6] = 0;
        lxCanTxMsg.data[7] = ucSummation_Check(ID,lxCanTxMsg.data,7);
        break;
    }
    case 0x4F:/*仪表写运行数据*/
    {
        lxCanTxMsg.data[1] = pBikeInfo->Display.Pas;
        lxCanTxMsg.data[2] = pBikeInfo->Display.Max_PWM;
        lxCanTxMsg.data[3] = (pBikeInfo->Display.Lamp << 2) | (pBikeInfo->Display.Battery_Low << 1) | (pBikeInfo->Display.Over_Speed);
        lxCanTxMsg.data[4] = 0;
        lxCanTxMsg.data[5] = 0;
        lxCanTxMsg.data[6] = 0;
        lxCanTxMsg.data[7] = ucSummation_Check(ID,lxCanTxMsg.data,7);
        break;
    }
    case 0x45:/*仪表写转把控制命令*/
    {
        lxCanTxMsg.data[1] = pBikeInfo->Display.Throttle_Percent;
        lxCanTxMsg.data[2] = 0;
        lxCanTxMsg.data[3] = 0;
        lxCanTxMsg.data[4] = 0;
        lxCanTxMsg.data[5] = 0;
        lxCanTxMsg.data[6] = 0;
        lxCanTxMsg.data[7] = ucSummation_Check(ID,lxCanTxMsg.data,7);
        break;
    }
    case 0x52:/*仪表读控制器配置参数*/
    case 0x54:/*仪表读控制器传感器状态命令*/
    case 0x56:/*仪表读控制器软硬件版本信息*/
    case 0x58:/*仪表读控制器生产信息命令*/
    case 0x12:/*设置电池进入休眠指令*/
    case 0x22:/*读电池电量*/
    case 0x24:/*读电池基本信息*/
    case 0x20:/*读电池故障信息*/
    case 0x26:/*读电池详细信息*/
    case 0x28:/*读电池充电信息*/
    case 0x2A:/*读电池版本信息*/
    case 0x2C:/*读电池生产信息*/
    {
        lxCanTxMsg.data[1] = 0;
        lxCanTxMsg.data[2] = 0;
        lxCanTxMsg.data[3] = 0;
        lxCanTxMsg.data[4] = 0;
        lxCanTxMsg.data[5] = 0;
        lxCanTxMsg.data[6] = 0;
        lxCanTxMsg.data[7] = ucSummation_Check(ID,lxCanTxMsg.data,7);
        break;
    }
    }


    MCF_WriteDataInFifo(gxCAN_TxQueue,(uint8_t *)&lxCanTxMsg,sizeof(can_tx_message_type),&lxState); /*将数据放入发送队列，排队发送*/
}

/******************************************************************************
** 功  能：处理发送消息
** 参  数：无
** 返回值：无
** 备  注：该函数需要500ms调用一次
******************************************************************************/
static void vCan_Send_Message(void)
{

    switch(geSend_Data_Type)
    {
    case Send_Stop:
    {
        return;						/*停止发送，直接退出*/
    }
    case Send_Run_Data:
    {
        /*判断是否超速*/
        if((usPROTOCOL_Get_Speed() > gxBikeInfo.Display.Speed_Limit * 10) && ((NO_LIMIT_WHEN_MAX == 0) || ((NO_LIMIT_WHEN_MAX == 1) && (gxBikeInfo.Display.Speed_Limit != CONFIG_SPEED_MAX))))
        {
            gxBikeInfo.Display.Over_Speed = 0x01;    /*置位超速标志*/
        }
        else
        {   /*速度降低到限速值-1以下时，清超速标志*/
            if(usPROTOCOL_Get_Speed() < (gxBikeInfo.Display.Speed_Limit - 1) * 10)
            {
                gxBikeInfo.Display.Over_Speed = 0x0;    /*清超速标志*/
            }
        }

        vCan_Send_DisplayMessage(ID_MCU,0x4F,&gxBikeInfo);      /*发送运行信息*/
        break;
    }
    case Send_Config_Data:
    case Send_Config_Data_OneTime:
    {
        vCan_Send_DisplayMessage(ID_MCU,0x43,&gxBikeInfo);      /*发送配置信息*/
        break;
    }
    }

    /*如果请求发送配置帧标记有效，则更改发送状态，下一次即开始发送配置帧*/
    if(gucRequestSendConfigData == 1)
    {
        gucRequestSendConfigData = 0;
        geSend_Data_Type = Send_Config_Data;
    }

    /*如果状态标记为只发送一次配置数据，那么发送完配置数据，并检测控制器已收到，将状态标记为发送运行数据*/
    if(geSend_Data_Type == Send_Config_Data_OneTime)
    {
        if(gucReceivedConfigFrame == 1)
        {
            geSend_Data_Type = Send_Run_Data;
            gucReceivedConfigFrame = 0;
        }
    }
}

/******************************************************************************
** 功  能：设置大灯状态
** 参  数：State-大灯状态。0-关闭，1-打开
** 返回值：无
** 备  注：所有协议通用
******************************************************************************/
void vPROTOCOL_Set_Lamp(uint8_t State)
{
    gxBikeInfo.Display.Lamp = State;/*灯状态*/

}


/******************************************************************************
** 功  能：设置档位
** 参  数：Pas-档位值，最大为9，最小为-1,-1表示助推档
** 返回值：无
** 备  注：
******************************************************************************/
void vPROTOCOL_Set_Pas(int8_t Pas)
{
    /*-1表示助推档*/
    if(Pas > 0)
    {
        gxBikeInfo.Display.Walk = 0;
        gxBikeInfo.Display.Pas = Pas;       /*按照实际挡位发送*/
        if(gtParam.Pas_Max == 3 && Pas < 4)
        {
            gxBikeInfo.Display.Max_PWM = 255 * gtParam.PWM0_3[Pas - 1] / 100;
        }
        else if(gtParam.Pas_Max == 5 && Pas < 6)
        {
            gxBikeInfo.Display.Max_PWM = 255 * gtParam.PWM0_5[Pas - 1] / 100;
        }
        else if(gtParam.Pas_Max == 7 && Pas < 8)
        {
            gxBikeInfo.Display.Max_PWM = 255 * gtParam.PWM0_7[Pas - 1] / 100;
        }
        else if(gtParam.Pas_Max == 9 && Pas < 10)
        {
            gxBikeInfo.Display.Max_PWM = 255 * gtParam.PWM0_9[Pas - 1] / 100;
        }
    }
    else if(Pas == 0)
    {
        gxBikeInfo.Display.Walk    = 0;
        gxBikeInfo.Display.Pas     = 0;
        gxBikeInfo.Display.Max_PWM = 0;
    }
    else
    {
        gxBikeInfo.Display.Pas  = 15;   /*15是助推档*/
        gxBikeInfo.Display.Walk = 1;
        gxBikeInfo.Display.Max_PWM = 40;    /*助推时，PWM值固定发40.原来程序就是固定发40.*/
    }
}



/******************************************************************************
** 功  能：设置限速值
** 参  数：Speed-限速值
** 返回值：无
** 备  注：本函数不对传入值的合理性做检查。请保证传入的值正确。
**         所有协议通用
******************************************************************************/
void vPROTOCOL_Set_Speed_Limit(uint8_t Speed)
{
    gxBikeInfo.Display.Speed_Limit = Speed;
}

/******************************************************************************
** 功  能：设置轮径
** 参  数：Wheel-轮径值，当Whee在8-34之间时，认为是轮径，单位Inch，当Wheel在51-255时，认为是轮周长，单位cm
** 返回值：无
** 备  注：
******************************************************************************/
void vPROTOCOL_Set_Wheel(uint8_t Wheel)
{
    if(Wheel < 35)
    {
        gxBikeInfo.Display.WheelSize = Wheel;
        gxBikeInfo.Display.Wheel_Length = 314UL * 254UL * Wheel / 1000;    /*根据轮径计算周长,mm*/
    }
    else if(Wheel > 50)
    {
        gxBikeInfo.Display.WheelSize = Wheel;
        gxBikeInfo.Display.Wheel_Length = Wheel * 10;   /*cm换算成mm*/
    }
}


/******************************************************************************
** 功  能：设置系统限流值
** 参  数：Current_Limit-系统限流值，分辨率：0.1A
** 返回值：无
** 备  注：
******************************************************************************/
void vPROTOCOL_Set_Current_Limit(uint16_t Current_Limit)
{
    gxBikeInfo.Display.Current_Limit = Current_Limit;
}

/******************************************************************************
** 功  能：设置缓启动参数
** 参  数：Start_Strength-启动强度
** 返回值：无
** 备  注：
******************************************************************************/
void vPROTOCOL_Set_Slow_Start(uint8_t Start_Strength)
{
    if(Start_Strength > 5)
    {
        Start_Strength = 5;
    }
    gxBikeInfo.Display.Slow_Start = Start_Strength;
}

/******************************************************************************
** 功  能：设置转把是否支持助推
** 参  数：Handle_Push-转把是否支持助推，0-正常转把，1-转把6km助推
** 返回值：无
** 备  注：
******************************************************************************/
void vPROTOCOL_Set_Handle_Walk(uint8_t Walk)
{
    gxBikeInfo.Display.Walk = Walk == 0 ? 0 : 1;
}

/******************************************************************************
** 功  能：设置转把是否支持分档
** 参  数：Handle_Segement-转把是否支持分档，0-转把不分档，1-转把分档
** 返回值：无
** 备  注：
** 适用协议：5S
******************************************************************************/
void vPROTOCOL_Set_Handle_Segement(uint8_t Handle_Segement)
{
    gxBikeInfo.Display.Handle_Segement = Handle_Segement == 0 ? 0 : 1;
}

/******************************************************************************
** 功  能：设置速度传感器数量
** 参  数：Speed_Sensor_Num-速度传感器数量，0-63
** 返回值：无
** 备  注：
******************************************************************************/
void vPROTOCOL_Set_Speed_Sensor_Num(uint8_t Speed_Sensor_Num)
{
    if(Speed_Sensor_Num > 63)
    {
        Speed_Sensor_Num = 63;
    }
    gxBikeInfo.Display.Speed_Sensor_Num = Speed_Sensor_Num;
}

/******************************************************************************
** 功  能：设置助力磁钢数
** 参  数：Assistant_Num-助力磁钢数
** 返回值：无
** 备  注：最大31磁钢
******************************************************************************/
void vPROTOCOL_Set_Assistant_Num(uint8_t Assistant_Num)
{
    if(Assistant_Num > 31)
    {
        Assistant_Num = 31; /*最大31磁钢*/
    }
    gxBikeInfo.Display.Assistant_Num = Assistant_Num;
}

/******************************************************************************
** 功  能：设置欠压标志
** 参  数：Battery_Low-欠压标志，0-不欠压，1-欠压
** 返回值：无
** 备  注：
******************************************************************************/
void vPROTOCOL_Set_Battery_Low(uint8_t Battery_Low)
{
    gxBikeInfo.Display.Battery_Low = Battery_Low == 0 ? 0 : 1;
}

/******************************************************************************
** 功  能：设置电池系统进入休眠
** 参  数：无
** 返回值：无
** 备  注：调用该函数后，会向BMS系统发送休眠指令
******************************************************************************/
void vPROTOCOL_Set_Battery_Idle(void)
{
    vCan_Send_DisplayMessage(ID_BMS,0x12,&gxBikeInfo);
}

/******************************************************************************
** 功  能：设置发送一次配置数据
** 参  数：无
** 返回值：无
** 备  注：本函数运行后，只发送一次配置数据。然后会转为发送运行数据
**         所有协议通用
******************************************************************************/
void vPROTOCOL_Send_Config_Data_OneTime(void)
{
    geSend_Data_Type = Send_Config_Data_OneTime;
    gucReceivedConfigFrame = 0;
}

/******************************************************************************
** 功  能：停止发送数据
** 参  数：无
** 返回值：无
** 备  注：本函数运行后，即停止发送数据。直到再次设置发送配置数据或发送运行数据
**         所有协议通用
******************************************************************************/
void vPROTOCOL_Send_Stop(void)
{
    gucRequestSendConfigData = 1;
}


/******************************************************************************
** 功  能：获取当前电流值
** 参  数：无
** 返回值：实际电流值的10倍。比如实际电流12.3A，返回123
** 备  注：所有协议通用
******************************************************************************/
uint16_t usPROTOCOL_Get_Current(void)
{
    return gxBikeInfo.MCU.Current * 2;  /*控制器发送的电流值单位是0.2A*/
}




/******************************************************************************
** 功  能：获取当前车速
** 参  数：无
** 返回值：实际车速*10.比如返回120，实际车速即12.0Km/h
** 备  注：所有协议通用
******************************************************************************/
uint16_t usPROTOCOL_Get_Speed(void)
{
    /*如果车轮转动一周的时间大于等于3500，或者等于0，或者通讯超时，或者轮径长度位0，即认为速度为0*/
    if((gxBikeInfo.MCU.Speed_Cnt >= 3500) || (gxBikeInfo.MCU.Speed_Cnt == 0) || (gxBikeInfo.ErrCode == 0x30) || gxBikeInfo.Display.Wheel_Length == 0)
    {
        return 0;
    }
    else
    {
        return gxBikeInfo.Display.Wheel_Length * 36UL / gxBikeInfo.MCU.Speed_Cnt;
    }
}

/******************************************************************************
** 功  能：获取错误代码
** 参  数：无
** 返回值：十六进制的错误代码
** 备  注：包括30错误代码（通信超时）
**         所有协议通用
******************************************************************************/
uint8_t ucPROTOCOL_Get_Errcode(void)
{
    if(gxBikeInfo.ErrCode > 0)
    {
        return gxBikeInfo.ErrCode;
    }
    else
    {
        if(gxBikeInfo.MCU.ErrorCode > 0x20 && gxBikeInfo.MCU.ErrorCode < 0x27)
        {
            return gxBikeInfo.MCU.ErrorCode;
        }
        else
        {
            return 0;
        }
    }

}

/******************************************************************************
** 功  能：获取电池容量
** 参  数：无
** 返回值：-1表示未获取到电池容量，电池容量，0-100%
** 备  注：协议不支持SOC，返回-1，为了兼容其他协议。
******************************************************************************/
int8_t cPROTOCOL_Get_Soc(void)
{
    /*如果从BMS读取到电池SOC，则返回对应值，否则返回-1，表示无效*/
    if(gxBikeInfo.Battery.Soc > -1)
    {
        return gxBikeInfo.Battery.Soc;
    }
    else
    {
        return -1;
    }
}

/******************************************************************************
** 功  能：获取BMS电压
** 参  数：无
** 返回值：BMS电压值，0.1V
** 备  注：
******************************************************************************/
uint16_t usPROTOCOL_Get_BMS_Voltage(void)
{
    return gxBikeInfo.Battery.Voltage / 100;
}

/******************************************************************************
** 功  能：获取BMS电流
** 参  数：无
** 返回值：BMS电流值，0.1V
** 备  注：
******************************************************************************/
int16_t sPROTOCOL_Get_BMS_Current(void)
{
    return gxBikeInfo.Battery.Current / 100;
}



/******************************************************************************
** 功  能：获取BMS的SOC
** 参  数：无
** 返回值：SOC，1%精度
** 备  注：
******************************************************************************/
int8_t cPROTOCOL_Get_BMS_SOC(void)
{
    return gxBikeInfo.Battery.Soc;
}

/******************************************************************************
** 功  能：获取BMS的剩余容量
** 参  数：无
** 返回值：剩余容量值，0.01Ah
** 备  注：
******************************************************************************/
uint16_t usPROTOCOL_Get_BMS_ResCap(void)
{
    return 0;
}

/******************************************************************************
** 功  能：获取BMS的循环次数
** 参  数：无
** 返回值：循环次数
** 备  注：
******************************************************************************/
uint8_t ucPROTOCOL_Get_BMS_CycleTimes(void)
{
    return 0;
}



/******************************************************************************
** 功  能：工厂指令的解析
** 参  数：无
** 返回值：无
** 备  注：
******************************************************************************/
void vPROTOCOL_Factory_Command(can_rx_message_type *pCanRxMsg)
{
    uint16_t lusResponse;

    switch(pCanRxMsg->extended_id)
    {
    case 0x1F18016E:/*校准光感，返回0x03F8016E*/
    {
        lusResponse = vPhotoDiode_Calibration();
        vPROTOCOL_Factory_Response(pCanRxMsg->extended_id,lusResponse);
        break;
    }
    case 0x1F18025D:/*校准电压，返回0x03F8025D*/
    {
        lusResponse = vVoltage_Calibration();
        vPROTOCOL_Factory_Response(pCanRxMsg->extended_id,lusResponse);
        break;
    }
    case 0x1F180371:/*校准时间，返回0x03F80371*/
    {
        vDateTime_Calibration(pCanRxMsg->data[3],pCanRxMsg->data[4],pCanRxMsg->data[5],pCanRxMsg->data[0],pCanRxMsg->data[1],pCanRxMsg->data[2]);
        lusResponse = 1234;
        vPROTOCOL_Factory_Response(pCanRxMsg->extended_id,lusResponse);
        break;
    }
    case 0x1F18048E:/*清ODO，返回0x03F8048E*/
    {
        vClear_ODO();
        lusResponse = 5678;
        vPROTOCOL_Factory_Response(pCanRxMsg->extended_id,lusResponse);
        break;
    }
    }
}

/******************************************************************************
** 功  能：工厂指令的返回
** 参  数：无
** 返回值：无
** 备  注：
******************************************************************************/
static void vPROTOCOL_Factory_Response(uint32_t Cmd,uint16_t Data)
{
    can_tx_message_type    lxCanTxMessage;

    lxCanTxMessage.id_type      = CAN_ID_EXTENDED;      /*扩展帧*/
    lxCanTxMessage.frame_type   = CAN_TFT_DATA;         /*数据帧*/
    lxCanTxMessage.dlc          = 2;                    /*数据长度*/
    lxCanTxMessage.extended_id  = 0x03F80000 | (Cmd & 0x0000FFFF);
    lxCanTxMessage.data[0]      = Data >> 8;
    lxCanTxMessage.data[1]      = (uint8_t)Data;

    /*调用发送函数进行发送*/
    can_message_transmit(CAN1,&lxCanTxMessage);
}

/******************************************************************************
** 功  能：复位通信超时计数变量
** 参  数：无
** 返回值：无
** 备  注：
******************************************************************************/
void vPROTOCOL_ResetCommunicationOverTime(void)
{
    gulCommunicationCnt = 0;        /*复位通信超时计数*/
    if(gxBikeInfo.ErrCode == 0x30)
    {
        gxBikeInfo.ErrCode = 0;
    }
}


/******************************************************************************
** 功  能：开机上电时，设置默认要发送给控制器的数据
** 参  数：无
** 返回值：无
** 备  注：
******************************************************************************/
void vPROTOCOL_Set_Value_When_PowerOn(void)
{
    vPROTOCOL_Set_Wheel(usGet_Wheel_Size(gtParam.Wheel_Diameter));  /*轮径，为和其他协议兼容，轮径是×10以后的值*/
    vPROTOCOL_Set_Pas(0);                                           /*开机LOGO界面发0档*/

    vPROTOCOL_Set_Speed_Limit(gtParam.Speed_Limit);                 /*限速*/

    vPROTOCOL_Set_Assistant_Num(gtParam.Assistant_Num);             /*助力磁钢数*/
    vPROTOCOL_Set_Current_Limit(gtParam.Current_Limit);             /*限流值*/
    vPROTOCOL_Set_Handle_Walk(CONFIG_HANDLE_PUSH);                  /*是否转把助推*/
    vPROTOCOL_Set_Handle_Segement(CONFIG_HANDLE_SEGEMENT);          /*转把是否分档*/
    vPROTOCOL_Set_Speed_Sensor_Num(gtParam.Speed_Sensor_Num);       /*速度磁钢数*/
    vPROTOCOL_Set_Slow_Start(gtParam.Start_Strength);               /*助力启动强度*/
    vPROTOCOL_Send_Config_Data_OneTime();                           /*开机时发送一次配置数据，然后自动切换为发送运行数据*/
}

/******************************************************************************
** 功  能：退出设置时，设置默认要发送给控制器的数据
** 参  数：无
** 返回值：无
** 备  注：
******************************************************************************/
void vPROTOCOL_Set_Value_When_ExitSetting(void)
{
    vPROTOCOL_Set_Wheel(usGet_Wheel_Size(gtParam.Wheel_Diameter));  /*轮径，为和其他协议兼容，轮径是×10以后的值*/

    vPROTOCOL_Set_Speed_Limit(gtParam.Speed_Limit);                 /*限速*/

    vPROTOCOL_Set_Assistant_Num(gtParam.Assistant_Num);             /*助力磁钢数*/

    vPROTOCOL_Set_Current_Limit(gtParam.Current_Limit);             /*限流值*/
    vPROTOCOL_Set_Handle_Walk(CONFIG_HANDLE_PUSH);                  /*是否转把助推*/
    vPROTOCOL_Set_Handle_Segement(CONFIG_HANDLE_SEGEMENT);          /*转把是否分档*/

    vPROTOCOL_Set_Speed_Sensor_Num(gtParam.Speed_Sensor_Num);       /*速度磁钢数*/
    vPROTOCOL_Set_Slow_Start(gtParam.Start_Strength);               /*助力启动强度*/
    vPROTOCOL_Send_Config_Data_OneTime();                           /*开机时发送一次配置数据，然后自动切换为发送运行数据*/

}


